﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Cherry.Agile.RpcService
{
    /// <summary>
    /// 服务处理调度处理器
    /// </summary>
    public class ServiceDispatcher
    {
        private static ITracer DefaultTracer = new EmptyTracer();

        /// <summary>
        /// 服务无法处理异常信息
        /// </summary>
        public static string FatalMsg = string.Empty;

        /// <summary>
        /// 字节数据处理入口
        /// </summary>
        /// <param name="requestBuffer">请求数据</param>
        /// <returns>响应数据</returns>
        public static byte[] Process(byte[] request)
        {
            ITracer t = DefaultTracer;
            ServiceConfigInfo config = ServiceConfigManager.ServiceConfig;
            //处理扩展插件
            ServiceExtentProcessor extProcessor = config.ExtentProcessor;
            ProcessContext context = null;
            try
            {
                if (ServiceConfigManager.ServiceConfig.TraceEnabled) //配置跟踪开启
                {
                    t = RuntimeTracer.Start("%PT%,");
                    context = new ProcessContext(t.AddTracePoint);//上下文支持写入跟踪
                }
                else
                {
                    context = new ProcessContext();
                }
                context.Reader = new BufferReader(request);

                extProcessor.ProcessOnStarting(context);

                //读版本，加载处理器
                //读版本信息
                int majorVer = context.Reader.ReadByte();
                int minorVer = context.Reader.ReadByte();
                Version version = new Version(majorVer, minorVer);

                if (!config.ServiceProcessor.ContainsKey(version))
                    throw new Exception("Not Support version" + version);
                IServiceProcessor processor = config.ServiceProcessor[version]; 
                context.Version = version;
                processor.Process(context);
                extProcessor.ProcessOnEnding(context);

                byte[] responseBuffer = context.Writer.ToArray();
                return responseBuffer;
            }
            catch (Exception ex)
            {
                FatalMsg = string.Format("{0},{1}", ex.Message, ex.StackTrace);
                extProcessor.ProcessTrace(ex,context);
                if (context != null && context.Writer != null)
                {
                    return context.Writer.ToArray();
                }
                else
                {
                    return new byte[] { 0xff };
                }
            }
            finally
            {
                string traceMessage = t.Stop();
                extProcessor.ProcessTrace(traceMessage,context);
            }
        }

    }
}
